package misc;

import gui.MainWindow;

import java.awt.Point;
import java.awt.geom.Point2D;
import java.io.*;
import java.util.ArrayList;
import java.util.Vector;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import org.jdom.*;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

import datas.Graph;
import datas.GraphInfos;
import datas.MetaGraph;
import datas.Vertex;

import javax.xml.parsers.*; 

public class GraphsFileManager {		
	private static int last_id = 0;
	private static Graph last_graph;
	private static GraphInfos last_infos;
	
	public static void Write(Graph graph, String _name, String _creator, String _desc) throws IOException {
		// Syntax: graph id name creator desc order
		Element graph_xml = new Element("graph");
		
		graph_xml.setAttribute("id", Integer.toString(graph.getId())); 
		graph_xml.setAttribute("name", _name); 
		graph_xml.setAttribute("creator", _creator); 
		graph_xml.setAttribute("desc", _desc); 
		graph_xml.setAttribute("order", Integer.toString(graph.getOrder()));
		
		for (Vertex v1: graph.getVertices()) {
			Element vertex = new Element("vertex");
			vertex.setAttribute("id", Integer.toString(v1.getIndex()));
			vertex.setAttribute("x", Double.toString(v1.getPosition().getX()));
			vertex.setAttribute("y", Double.toString(v1.getPosition().getY()));
			
			graph_xml.addContent(vertex);
		}
		
		for (Vertex v1: graph.getVertices()) {		
			for (Vertex v2: graph.getEdges().get(v1)) {
				Element edge = new Element("edge");
				edge.setAttribute("from", Integer.toString(v1.getIndex()));
				edge.setAttribute("to", Integer.toString(v2.getIndex()));				

				graph_xml.addContent(edge);
			}
		}
		
		// Externalization
		Document main = new Document();
		
		File file = new File(MainWindow.GRAPHS_FILE);
		if (!file.exists()) {
			try {
				XMLOutputter sortie = new XMLOutputter(Format.getPrettyFormat());
				sortie.output(new Element("datas"), new FileOutputStream(MainWindow.GRAPHS_FILE));
			}
			catch(Exception e) {}
		}
		
		SAXBuilder sxb = new SAXBuilder();
	      try {
	         main = sxb.build(new File(MainWindow.GRAPHS_FILE));
	         
	         Element current_root = main.getRootElement();
	 	     current_root.addContent(graph_xml);

	 			
	 		 XMLOutputter serializer = new XMLOutputter(Format.getPrettyFormat());
	 		 serializer.output(current_root, new FileOutputStream(MainWindow.GRAPHS_FILE));	 	    
	 	  }
	      catch(Exception e){}	    
	}
	
	public static int getLastGraphId() {			
		try {			
			// Creating a parser
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
		
			// Reading file with default handler
			File xml_file = new File(MainWindow.GRAPHS_FILE);
	 
			DefaultHandler handler = new DefaultHandler() {	
				int id = 0;
				
				public void startDocument() throws SAXException {
					// Invoked while starting reading the XML file
				}
	
				public void endDocument() throws SAXException {
					// Invoked while ending reading the XML file
				}
	
				public void startElement(String uri, String local_name, String q_name, Attributes attributes) throws SAXException {
					if ((q_name.compareToIgnoreCase("graph")) == 0)
						GraphsFileManager.this.last_id = Integer.parseInt(attributes.getValue(0));	
				}
	
				public void endElement(String uri, String local_name, String q_name) throws SAXException {
				
				}
	
				public void characters(char[] ch, int start, int length) throws SAXException {
					// Getting text within a node
				}
			};

			parser.parse(xml_file, handler);			
		} 
		
		catch (Exception e) {}
		
		return last_id;
	}
	
	public static ArrayList<MetaGraph> Read() {
		final ArrayList<MetaGraph> meta_graphs = new ArrayList<MetaGraph>();
		
		try {			
			// Creating a parser
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
		
			// Reading file with default handler
			File xml_file = new File(MainWindow.GRAPHS_FILE);
	 
			DefaultHandler handler = new DefaultHandler() {	
				int last_id = 0;
				
				public void startDocument() throws SAXException {
					// Invoked while starting reading the XML file
				}
	
				public void endDocument() throws SAXException {
					// Invoked while ending reading the XML file
					Vertex.changeID(last_id+1);
				}
	
				public void startElement(String uri, String local_name, String q_name, Attributes attributes) throws SAXException {
					if ((q_name.compareToIgnoreCase("graph")) == 0) {
						GraphsFileManager.this.last_graph = new Graph();
						GraphsFileManager.this.last_infos = new GraphInfos();
						
						// Syntax: graph id name creator desc
						GraphsFileManager.this.last_graph.setId(Integer.parseInt(attributes.getValue(0)));
						GraphsFileManager.this.last_infos.setName(attributes.getValue(1));
						GraphsFileManager.this.last_infos.setCreator(attributes.getValue(2));
						GraphsFileManager.this.last_infos.setDescription(attributes.getValue(3));						
					}
						
					
					else if ((q_name.compareToIgnoreCase("vertex")) == 0) {
						last_id = Integer.parseInt(attributes.getValue(0));
						
						GraphsFileManager.this.last_graph.addVertex(Integer.parseInt(attributes.getValue(0)), new Point2D.Double(Double.parseDouble(attributes.getValue(1)), Double.parseDouble(attributes.getValue(2))));
					}
					
					else if ((q_name.compareToIgnoreCase("edge")) == 0) {						
						GraphsFileManager.this.last_graph.addEdge(Integer.parseInt(attributes.getValue(0)), Integer.parseInt(attributes.getValue(1)));
					}
				}
	
				public void endElement(String uri, String local_name, String q_name) throws SAXException {
					if ((q_name.compareToIgnoreCase("graph")) == 0)
						meta_graphs.add(new MetaGraph(GraphsFileManager.this.last_graph, GraphsFileManager.this.last_infos));
				}
	
				public void characters(char[] ch, int start, int length) throws SAXException {
					// Getting text within a node
				}
			};

			parser.parse(xml_file, handler);
		} 
		
		catch(ParserConfigurationException e) {
			// Error from parser's configuration			
			e.getMessage();			
		} 
		
		catch(SAXException e) {
			// Error while parsing
			System.out.println(e.getMessage());
		} 
		
		catch(IOException e) {
			// IO error
	        e.getMessage();
	    }
	     
		return meta_graphs;
	}
}
